#! /usr/bin/env perl

###########################################################################
#
# vbranch
#
###########################################################################
#
# This command either changes your current working copy from the trunk to a branch (like svn switch), or
# creates a new branch for you based on your current working copy (like svn copy).  THIS COMMAND DOES NOT YET
# WORK WITH CVS!
#
# #########################################################################
#
# All the code herein is released under the Artistic License
#		( http://www.perl.com/language/misc/Artistic.html )
# Copyright (c) 2004-2009 Barefoot Software, Copyright (c) 2004-2005 ThinkGeek
#
###########################################################################

use strict;
use warnings;

use VCtools::Base;
use VCtools::Args;
use VCtools::Common;


#################################
# OPTIONS AND ENVIRONMENT VARS
#################################

VCtools::switch('create', 'c', 'create the new branch before switching to it (conflicts with -s)');
VCtools::switch('show', 's', 'just show what branch files belong to (conflicts with -c)');
VCtools::switch('message', 'm', 'specify commit message instead of using editor (only works with -c)', 'commit_message');
VCtools::args('branch', 'opt', "name of branch to switch to (can't exist with -c, must exist without, unused with -s)");
VCtools::args('files', 'optlist', 'file(s) and/or directory/ies to show (default: .); ONLY WORKS WITH -s');
VCtools::getopts();

# remember, directories are files too
my @files = VCtools::files();
# have to check a few things up here to make sure we get @files situated right
if (VCtools::create())
{
	VCtools::fatal_error("can't mix -c and -s") if VCtools::show();

	debuggit(2 => "comparing to . :", VCtools::projpath("."));
	if (VCtools::projpath(".") ne './')
	{
		# this means we're not in our TLD
		VCtools::fatal_error("You need to be in the TLD for your project to create a branch; try vcd with no args");
	}

	if (@files)
	{
		# if we're going to create, we need to do the whole schlemiel
		VCtools::fatal_error("You can't really restrict branch creation to certain files");
	}

	VCtools::prompt_to_continue("Going to create the branch, then convert your entire working copy to that branch.");
	@files = (".");
}
elsif (VCtools::show())
{
	# since -s doesn't use branch, anything in VCtools::branch() is actually a file
	unshift @files, VCtools::branch() if VCtools::branch();

	# we'll actually pay attention to @files in this one
	# (but . is still the default)
	@files = ('.') unless @files;
}
else
{
	# not creating, so check a few things

	if (not @files)
	{
		VCtools::prompt_to_continue("Your entire local copy from this directory down will be converted to the branch!");
		@files = (".");
	}
}
print STDERR "switch files: @files\n" if DEBUG >= 3;


#################################
# CHECK FOR ERRORS
#################################

VCtools::verify_files_and_group(@files);
VCtools::check_branch_errors();

# make sure that branch either exists or doesn't, as appropriate
# (but not if we're just doing a show)
unless (VCtools::show())
{
	if (VCtools::create())
	{
		if (VCtools::branch_exists_in_vc(VCtools::branch()))
		{
			VCtools::fatal_error("branch " . VCtools::branch() . " already exists; cannot create");
		}
	}
	else
	{
		unless (VCtools::branch_exists_in_vc(VCtools::branch()))
		{
			VCtools::fatal_error("no such branch " . VCtools::branch());
		}
	}
}

# get statuses for everything at once (quicker that way)
# for -s:
# 		we have to show branches, because that's the point of the whole exercise
# 		we don't care about outdated, and it'll just slow us down, so don't do that
# 		recursive doesn't make any sense, so ignore it
# for -c or without either:
# 		ALWAYS recursive!
my $opts = VCtools::show() ? { SHOW_BRANCHES => 1, NO_OUTDATED => 1, DONT_RECURSE => 1 } : { DONT_RECURSE => 0 };
my @all_files = VCtools::cache_file_status(@files, $opts);

foreach my $file (@files)
{
	# can skip these errors if -s and -i both specified
	next if VCtools::show() and VCtools::ignore_errors();

	VCtools::fatal_error("$file is not in VC") unless VCtools::exists_in_vc($file);
}

unless (VCtools::show())
{
	my @mod_files;
	foreach my $file (@all_files)
	{
		push @mod_files, $file if VCtools::modified_from_vc($file);
	};
	if (@mod_files)
	{
		VCtools::list_files("are modified from the repository versions", @mod_files);
		VCtools::prompt_to_continue("If you want these mods to go into the branch, continue.",
				"If you want the mods to stay in the trunk, stop now and vcommit before you vbranch.");
	}
}


#################################
# MAIN
#################################

if (VCtools::show())
{
	print "\n";
	foreach (@files)
	{
		print "$_ : ";
		VCtools::print_branch($_);
		print "\n";
	}
	print "\n";
	exit(0);
}

if (VCtools::create())
{
	VCtools::create_branch(VCtools::branch());
}

VCtools::switch_to_branch(VCtools::branch(), @files);
VCtools::initialize_branch(VCtools::branch()) if VCtools::create();

print "done\n" unless $?;


#################################
# SUBS
#################################
